package com.xagent.agent;

import com.xagent.agent.agent.Agent;
import com.xagent.core.Entry;
import com.xagent.core.Properties;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.instrument.Instrumentation;
import java.net.URL;
import java.net.URLDecoder;
import java.util.jar.JarFile;

/**
 * Author: 4ut15m
 * Agent的一些预处理操作
 * 主要是所需jar包的加载、进入engine.
 */
public class Launcher {
    private String jarPath;
    private Instrumentation instrumentation;

    public Launcher(Instrumentation instrumentation, String args) {
        this.instrumentation = instrumentation;
    }

    public void start() throws Exception {
        jarPath = parseJarPath();
        /**
         * 添加core与engine进jvm
         * */
        addJarToBootStrap(instrumentation, getCorePath(), true);
        addJarToBootStrap(instrumentation, getEnginePath(), false);

        Class<?> aClass = Class.forName(Properties.COMMON_ENGINE_ENTRY_CLASS);
        Entry o = (Entry) aClass.newInstance();
        o.entrance(instrumentation, jarPath);


    }

    public String parseJarPath() {
        /**
         * 如果有指定agent路径，则以agent路径下的jar为准，否则以本地agent.jar所在路径为准
         * */
        String agentPath = System.getProperty(Properties.XAGENT_AGENT_PATH);

        if (agentPath == null || "".equals(agentPath)) {
            String localJarPath = getLocalJarPath();
            return localJarPath;
        }

        return agentPath;
    }

    /**
     * 将jar包加载进JVM中
     *
     * @param instrumentation inst实例
     * @param corePath        core.jar的路径
     */
    public void addJarToBootStrap(Instrumentation instrumentation, String corePath) throws IOException {
        addJarToBootStrap(instrumentation, corePath, true);
    }

    /**
     * 将jar包加载进JVM中
     *
     * @param instrumentation inst实例
     * @param jarPath         待加载jar的路径
     * @param isCore          说明是不是core.jar，true则说明要加载的是core.jar
     */
    public void addJarToBootStrap(Instrumentation instrumentation, String jarPath, boolean isCore) throws IOException {
        if (isCore) {
            try {
                Class.forName("com.xagent.core.GlobalEntry");
                return;
            } catch (ClassNotFoundException e) {
                // 说明没有加载过core
            }
        }

        instrumentation.appendToBootstrapClassLoaderSearch(new JarFile(jarPath));

    }

    /**
     * @return 返回当前jar的绝对路径
     */
    public String getLocalJarPath() {
        URL u = Agent.class.getProtectionDomain().getCodeSource().getLocation();
        String path = "";
        try {
            path = URLDecoder.decode(u.getFile().replace("+", "%2B"), "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        if (path.lastIndexOf("/") != -1) {
            path = path.substring(0, path.lastIndexOf("/"));
        }

        return path;
    }

    public String getCorePath() {
        return jarPath + File.separator + "xagent-core.jar";
    }

    public String getEnginePath() {
        return jarPath + File.separator + "xagent-engine.jar";
    }

}
